package apigateway.project.core.helper;

import apigateway.project.commen.config.Rule;
import apigateway.project.commen.enums.Code;
import apigateway.project.commen.exception.RuleNotFoundException;
import apigateway.project.commen.utils.Netutils;
import apigateway.project.core.CacheConfig;
import apigateway.project.core.context.GlobalContext;
import apigateway.project.core.predicate.GatewayPredicateChain;
import apigateway.project.core.predicate.GatewayPredicateChainFactory;
import apigateway.project.core.predicate.PredicateChainFactory;
import apigateway.project.core.request.GlobalRequest;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.*;

import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.List;

/**
 * 负责处理请求封装
 */
public class RequestHelper {
    public static GlobalContext buildContext(ChannelHandlerContext ctx, FullHttpRequest httpRequest) {
        //封装请求
        GlobalRequest request = buildRequest(ctx, httpRequest);
        //匹配路由规则
        Rule rule = rulesMapping(request);
        if(rule == null) {
            throw new RuleNotFoundException(Code.RULE_NO_MATCHED);
        }
        GlobalContext globalContext = new GlobalContext(ctx,HttpUtil.isKeepAlive(httpRequest),request,rule,0);
        return globalContext;
    }

    /**
     * 匹配路由规则
     * @param request
     * @return
     */
    private static Rule rulesMapping(GlobalRequest request) {
        //遍历所有断言,匹配路由规则
        CacheConfig cacheConfig = CacheConfig.getCacheConfig();
        List<Rule> rules = cacheConfig.getAllRules();
        for (Rule rule : rules) {
            PredicateChainFactory chainFactory= new GatewayPredicateChainFactory();
            GatewayPredicateChain chain = chainFactory.createChain(rule);
            boolean isMatched = chain.doPredicates(request, rule);
            if (isMatched) {
                return rule;
            }
        }
        return null;
    }

    private static GlobalRequest buildRequest(ChannelHandlerContext ctx, FullHttpRequest httpRequest) {
        HttpHeaders headers = httpRequest.headers();

        String host = headers.get(HttpHeaderNames.HOST);
        String uri = httpRequest.getUri();
        HttpMethod method = httpRequest.getMethod();
        String clientIp = Netutils.getClientIp(ctx,headers);
        Charset charset = HttpUtil.getCharset(httpRequest, StandardCharsets.UTF_8);
        CharSequence type = HttpUtil.getMimeType(httpRequest);
        String contentType = null;
        if(type != null){
            contentType = type.toString();
        }

        return new GlobalRequest(host,uri,method,clientIp,charset,contentType,headers,httpRequest);
    }
}
